昨天我設計好了列表元件,
但發現列表缺少新增、修改、刪除的功能。
因此,我決定在原本的元件上做一些調整。
不過這邊發現有個BUG
昨天寫的程式輸入會有問題
後來經過檢查以後發現是form變更會影響getGroupList的結果
所以這邊調整成getGroupList只在初始化的時候產生一次
// form-input.component.ts
@Input() pageSetting!: PageSetting
fieldObj!: object;
groupList!: any[]; // 新增變數控制
innerForm = this.fb.group({});
constructor(private fb: FormBuilder,
public shareService: ShareService,
private validatorService: ValidatorService
) { }
private destroy$ = new Subject<void>(); // 用來發出結束通知
ngOnChanges(): void
{
this.pageSetting.form = this.fb.group({});
this.innerForm = this.fb.group({});
this.pageSetting.fieldSettings.forEach(setting =>
{
let newControl = this.fb.control(setting.defaultValue) as FormControl;
if (setting.validator && setting.validator?.length > 0)
{
if (!!setting.validator.find(v => v == 'required')) setting.required = true;
newControl.addValidators(this.validatorService.getValidators(setting.validator))
}
if (setting.groupType == 'list' && !!setting.groupName)
{
if (!this.innerForm.contains(setting.groupName))
{
let newFormArray = new FormArray([])
this.innerForm.addControl(setting.groupName, newFormArray);
this.pageSetting.form?.addControl(setting.groupName, newFormArray);
}
return
}
(this.pageSetting.form as FormGroup).addControl(setting.name, newControl);
if (!setting.groupName)
{
this.innerForm.addControl(setting.name, newControl);
} else
{
if (!this.innerForm.contains(setting.groupName))
{
this.innerForm.addControl(setting.groupName, new FormGroup({}));
}
(this.innerForm.get(setting.groupName) as FormGroup).addControl(setting.name!, this.pageSetting.form?.get(setting.name));
(this.pageSetting.form?.get(setting.name) as FormGroup)
.valueChanges.pipe(takeUntil(this.destroy$)).subscribe(v =>
{
this.pageSetting.form?.updateValueAndValidity();
})
}
});
this.getGroupList(this.innerForm); // 調整
}
// form-input.component.html
<div
*ngFor="let fieldObj of groupList"
[ngClass]="{
'col-6': shareService.typeof(fieldObj) === 'string',
'col-12': shareService.typeof(fieldObj) !== 'string'
}"
>
上面原本使用getGroupList的部分改成採用groupList
然後,原本的輸入框會改成純顯示,
並在最下方新增一排輸入欄位,用來添加新的資料。
當使用者新增資料時,資料會被加到 inputFormArray 裡面。
此外,原本資料的旁邊會增加一個「修改」按鈕,點擊後,
該行的資料會從顯示狀態變成可輸入狀態,
且輸入模板會複製原本該行的資料進行編輯。
// list.component.html
<table [formGroup]="inputForm">
<thead>
<tr>
<th *ngFor="let title of titleArr">
{{ title }}
</th>
</tr>
</thead>
<tbody formArrayName="{{ listKey }}">
<tr
*ngFor="let row of inputFormArray.controls; let i = index"
[formGroupName]="i"
>
<ng-container
*ngTemplateOutlet="
editRowNum != i ? displayRow : editRow;
context: editRowNum != i
? { inTeplateForm: row, index: i }
: { inTeplateForm: subFormGroup, index: i }
"
></ng-container>
</tr>
<tr>
<ng-container
*ngTemplateOutlet="
editRowNum < inputFormArray.controls.length ? emptyRow : addRow;
context: { inTeplateForm: subFormGroup }
"
>
</ng-container>
</tr>
</tbody>
</table>
<ng-template #emptyRow></ng-template>
<ng-template #displayRow let-fg="inTeplateForm" let-i="index">
<td *ngFor="let key of Object.keys(fg.value)">
{{ fg.get(key)?.value }}
</td>
<button (click)="edit(i)">編輯</button>
<button (click)="delete(i)">刪除</button>
</ng-template>
<ng-template #editRow let-fg="inTeplateForm" let-i="index">
<ng-container *ngIf="fg">
<td *ngFor="let key of Object.keys(fg?.value)">
<app-field
[fieldSetting]="this.shareService.getSetting(this.fieldSettings, key)"
[control]="shareService.getControl(fg, key)"
></app-field>
</td>
<td>
<button (click)="save(i)">儲存</button>
<button (click)="cancel()">取消</button>
</td>
</ng-container>
</ng-template>
<ng-template #addRow let-fg="inTeplateForm">
<ng-container *ngIf="fg">
<td *ngFor="let key of Object.keys(fg?.value)">
<app-field
[fieldSetting]="this.shareService.getSetting(this.fieldSettings, key)"
[control]="shareService.getControl(fg, key)"
></app-field>
</td>
<td>
<button (click)="add()">新增</button>
</td>
</ng-container>
</ng-template>
// list.component.ts
add()
{
this.inputFormArray.push(this.fb.group(this.subFormGroup.value));
this.editRowNum = this.inputFormArray.value.length;
}
delete(index: number)
{
this.inputFormArray.removeAt(index);
}
cancel()
{
this.subFormGroup.reset();
this.editRowNum = this.inputFormArray.value.length;
}
edit(index: number)
{
this.editRowNum = index;
this.subFormGroup.patchValue(this.inputFormArray.controls[index].value);
}
save(index: number)
{
this.inputFormArray.controls[index].patchValue(this.subFormGroup.value);
this.subFormGroup.reset();
this.editRowNum = this.inputFormArray.value.length;
}
新增和修改功能可以共用同一個模板,
這個模板可以通過 subFormGroup 的 form 來進行處理。
除了編輯功能,還會提供「刪除」按鈕,
讓使用者可以點擊後刪除該筆資料。
雖然我原本想做一個簡單的新增、修改、刪除功能,
但這個模板的結構似乎變得有點複雜了。
因此,我也有另一個想法,是否可以改用彈窗來處理這些操作。
使用彈窗的話,模板規則就不用那麼複雜,或許會更簡單易行。
我們可以在明天再來討論和決定具體的實現方式。
今日程式:day25